home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’96
/
VideoFolder 1.0a
/
Source
/
ConvertToFinderIconPict.cp
next >
Wrap
Text File
|
1996-06-22
|
12KB
|
409 lines
#include "ConvertToFinderIconPict.h"
#include "Finder.h"
#include "MoreFilesExtras.h"
#include <QDOffscreen.h>
#include <Palettes.h>
#include <QDOffscreen.h>
#include <stdio.h>
const short kCustomIconResID = -16455;
CFinderIconPicture::CFinderIconPicture ( short vRefNum, long dirID ) :
mVRefNum ( vRefNum ),
mDirID ( dirID ),
mPix ( nil )
{
}
CFinderIconPicture::~CFinderIconPicture ( )
{
TearDownPixMap();
}
void CFinderIconPicture::AddCustomIconResource ( short refNum, OSType resType, GWorldPtr pic, Rect& r, unsigned short depth )
{ Handle h = MakeIcon ( pic, & r, depth, 32 );
if ( h )
AddResource ( h, resType, kCustomIconResID, "\p" );
}
void CFinderIconPicture::CreateIconResourcesToFile ( GWorldPtr pic, short refNum, Rect& r )
{
Handle iconPound = MakeICN_pound ( pic, pic, & r, 32 );
AddResource ( iconPound, 'ICN#', kCustomIconResID, "\p" );
AddCustomIconResource ( refNum, 'icl8', pic, r, 8 );
// AddCustomIconResource ( refNum, 'icl4', pic, r, 4 );
}
static inline void PLstrcpy ( StringPtr dest, const StringPtr source )
{
BlockMoveData ( source, dest, source[0] + 1 );
}
static void UniqueXYFilename ( unsigned short x, unsigned short y, StringPtr str )
{ const unsigned char spaceChar = ' ';
const unsigned char nonBreakingSpaceChar = 0x01;
str[0] = 0;
for ( short i = 14; i >= 0 ; i -- )
str[ ++ str[0] ] = ( y & ( 1 << i ) ) ? spaceChar : nonBreakingSpaceChar;
for ( short i = 14; i >= 0 ; i -- )
str[ ++ str[0] ] = ( x & ( 1 << i ) ) ? spaceChar : nonBreakingSpaceChar;
}
void CFinderIconPicture::CreateTiledFile ( GWorldPtr pic, unsigned short x, unsigned short y )
{ FSSpec spec;
Str255 fileName = "\pFile ";
UniqueXYFilename ( x, y, fileName );
if ( FSMakeFSSpec ( mVRefNum, mDirID, fileName, & spec ) == noErr )
FSpDelete ( & spec );
FSpCreateResFile ( & spec, 'VFol', 'VFI#', smRoman );
FInfo fileInfo;
if ( FSpGetFInfo ( & spec, & fileInfo ) == noErr )
{
fileInfo.fdLocation.h = x;
fileInfo.fdLocation.v = y;
fileInfo.fdFlags = kHasCustomIcon | kNameLocked | kHasBeenInited;
FSpSetFInfo ( & spec, & fileInfo );
}
short refNum = FSpOpenResFile ( & spec, fsRdWrPerm );
if ( refNum && ResError() == noErr )
{ Rect r;
r.top = y;
r.bottom = y + 32;
r.left = x;
r.right = x + 32;
CreateIconResourcesToFile ( pic, refNum, r );
CloseResFile ( refNum );
}
}
void CFinderIconPicture::DeleteExistingIcons ( )
{
CInfoPBRec getCatInfoPB;
getCatInfoPB.dirInfo.ioFDirIndex = 1; /* get first item */
OSErr err = noErr;
do
{ Str255 itemName = "\p";
/* prepare to delete directory */
getCatInfoPB.dirInfo.ioNamePtr = itemName;
getCatInfoPB.dirInfo.ioVRefNum = mVRefNum;
getCatInfoPB.dirInfo.ioDrDirID = mDirID; /* in this directory */
OSErr err = PBGetCatInfoSync(&(getCatInfoPB));
if ( err == noErr )
{
getCatInfoPB.dirInfo.ioFDirIndex ++;
/* We have an item. Is it a file or directory? */
if ( (getCatInfoPB.dirInfo.ioFlAttrib & ioDirMask) == 0 )
{
if ( getCatInfoPB.hFileInfo.ioFlFndrInfo.fdType == 'VFI#' && getCatInfoPB.hFileInfo.ioFlFndrInfo.fdCreator == 'VFol' )
{
err = PBHDeleteSync( (HParamBlockRec*) &(getCatInfoPB)); /* delete this item */
if ( err == noErr )
getCatInfoPB.dirInfo.ioFDirIndex --;
}
if ( err == fLckdErr )
{
(void) PBHRstFLockSync( (HParamBlockRec*) &(getCatInfoPB)); /* unlock it */
err = PBHDeleteSync( (HParamBlockRec*) &(getCatInfoPB)); /* and try again */
if ( err == noErr )
getCatInfoPB.dirInfo.ioFDirIndex --;
}
}
}
} while ( err == noErr );
}
void CFinderIconPicture::AcceptPict ( GWorldPtr pic )
{
// "Tile" across the picture, creating icons for each file
// DeleteDirectoryContents ( mVRefNum, mDirID, "\p" );
// DeleteExistingIcons ();
Rect gWorldRect = pic->portRect;
for ( unsigned short y = gWorldRect.top; y < gWorldRect.bottom; y += 32 )
{
for ( unsigned short x = gWorldRect.left; x < gWorldRect.right; x += 32 )
CreateTiledFile ( pic, x, y );
}
}
Handle CFinderIconPicture::MakeICN_pound(GWorldPtr gwp, GWorldPtr maskP, Rect *srcRect, short iconDimension)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
this returns a handle to the image data for an icon and it's mask, of size iconDimension x iconDimension.
The icon is created by copying the srcRect of srcGWorld into a PixMap.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
{ Handle icon;
Handle iconMask;
Size iconSize;
icon = MakeIcon(gwp, srcRect,1,iconDimension);
// Once we've made the icon, create a mask of the icon which has 1 bits
// for every place 'inside' the enclosing rectangle.
if(icon)
{ Handle iconMask = NewHandle ( GetHandleSize ( icon ) );
for ( unsigned i = GetHandleSize ( iconMask ); i > 0; )
(*iconMask)[--i] = 0xff;
if(iconMask)
{
iconSize = GetHandleSize(icon);
SetHandleSize(icon, iconSize + GetHandleSize(iconMask));
// CheckError("\pSetHandleSize fail.",MemError());
BlockMove(*iconMask, (Ptr)(((long)*icon) + iconSize), GetHandleSize(iconMask));
DisposeHandle(iconMask);
}
}
return icon;
}
Handle CFinderIconPicture::MakeIcon(GWorldPtr srcGWorld, Rect* srcRect, short dstDepth, short iconSize)
/*
Creates a handle to the image data for an icon, or nil if an error.
The source image is specified by GWorld and regtangle defining the area
to create the icon from.
The type of icon is specified by the depth and Size paramters.
iconSize is used for both height and width.
For example, to create an Icl8 pass 8 for dstDepth and 32 for iconSize.
to create an ics8 pass 8 for the dstDepth and 16 for iconSize.
to create an ICON pass 1 for the dstDepth and 32 for iconSize.
*/
{
GWorldPtr saveWorld;
GDHandle saveHandle;
long bytesPerRow;
long imageSize;
Handle dstHandle;
Rect iconFrame;
QDErr err;
Rect gWorldRect;
Rect sourceRect = *srcRect;
GetGWorld(&saveWorld,&saveHandle); // save Graphics env state
SetGWorld(srcGWorld,nil);
iconFrame.top = 0;
iconFrame.left = 0;
iconFrame.bottom = iconSize;
iconFrame.right = iconSize;
if ( mPix && ( ( (**mPix).pixelSize != dstDepth ) || ! EqualRect( & (**mPix).bounds, &iconFrame ) ) )
TearDownPixMap();
// make a gworld for the icl resource
if ( ! mPix )
{
mPix = (PixMapHandle) NewHandleClear(sizeof(PixMap));
/* See Tech Note #120 - for info on creating a PixMap by hand as SetUpPixMap
does. SetUpPixMap was taken from that Tech Note....
*/
// GWorldPtr destGWorld = nil;
// err = NewGWorld ( & destGWorld, dstDepth, & iconFrame, GetCTable(dstDepth+200), nil, useTempMem );
CTabHandle colorTableH = GetCTable(dstDepth);
err = SetUpPixMap(dstDepth,&iconFrame,colorTableH, mPix);
DisposeCTable ( colorTableH );
if(err)
return nil;
}
LockPixels( GetGWorldPixMap(srcGWorld) );
LockPixels(mPix);
gWorldRect = srcGWorld->portRect;
if ( sourceRect.top < gWorldRect.top )
{
iconFrame.top = gWorldRect.top - sourceRect.top;
sourceRect.top = gWorldRect.top;
}
if ( sourceRect.left < gWorldRect.left )
{
iconFrame.left = gWorldRect.left - sourceRect.left;
sourceRect.left = gWorldRect.left;
}
if ( sourceRect.bottom > gWorldRect.bottom )
{
iconFrame.bottom = iconFrame.bottom - ( sourceRect.bottom - gWorldRect.bottom );
sourceRect.bottom = gWorldRect.bottom;
}
if ( sourceRect.right > gWorldRect.right )
{
iconFrame.right = iconFrame.right - ( sourceRect.right - gWorldRect.right );
sourceRect.right = gWorldRect.right;
}
CopyBits( (BitMap*) *srcGWorld->portPixMap, (BitMap*) *mPix,
& sourceRect, &iconFrame, srcCopy | ( dstDepth > 4 ) ? ditherCopy : 0, nil);
UnlockPixels(GetGWorldPixMap(srcGWorld));
bytesPerRow = ((dstDepth * ((**mPix).bounds.right - (**mPix).bounds.left) + 31) / 32) * 4;
imageSize = (bytesPerRow) * ((**mPix).bounds.bottom - (**mPix).bounds.top);
SetZone ( ApplicationZone() );
dstHandle = NewHandleClear(imageSize);
err = MemError ();
if(err || dstHandle == nil)
{
return nil;
}
HLock(dstHandle);
BlockMove(GetPixBaseAddr(mPix),*dstHandle,imageSize);
HUnlock(dstHandle);
UnlockPixels(mPix);
// TearDownPixMap(mPix);
// Restore graphics env to previous state
SetGWorld(saveWorld,saveHandle);
HNoPurge(dstHandle);
return dstHandle;
}
void CFinderIconPicture::TearDownPixMap()
{
if ( mPix )
{
// We really need to do more.... BUT It is the thought that counts..
if ( (** mPix).pmTable )
DisposeCTable ( (**mPix).pmTable );
DisposePtr ( (**mPix).baseAddr );
DisposeHandle( (Handle) mPix );
mPix = nil;
}
}
#define kDefaultRes 0x00480000 /* Default resolution is 72 DPI; Fixed type */
OSErr CFinderIconPicture::SetUpPixMap(
short depth, /* Desired number of bits/pixel in off-screen */
Rect *bounds, /* Bounding rectangle of off-screen */
CTabHandle colors, /* Color table to assign to off-screen */
PixMapHandle aPixMap /* Handle to the PixMap being initialized */
)
{
CTabHandle newColors; /* Color table used for the off-screen PixMap */
Ptr offBaseAddr; /* Pointer to the off-screen pixel image */
OSErr error; /* Returns error code */
short bytesPerRow; /* Number of bytes per row in the PixMap */
error = noErr;
newColors = nil;
offBaseAddr = nil;
bytesPerRow = ((depth * (bounds->right - bounds->left) + 31) / 32) * 4;
/* Clone the clut if indexed color; allocate a dummy clut if direct color*/
if (depth <= 8)
{
newColors = colors;
error = HandToHand((Handle *) &newColors);
}
else
{
newColors = (CTabHandle) NewHandle(sizeof(ColorTable) -
sizeof(CSpecArray));
error = MemError();
}
if (error == noErr)
{
/* Allocate pixel image; long integer multiplication avoids overflow */
offBaseAddr = NewPtrClear((unsigned long) bytesPerRow * (bounds->bottom -
bounds->top));
if (offBaseAddr != nil)
{
/* Initialize fields common to indexed and direct PixMaps */
(**aPixMap).baseAddr = offBaseAddr; /* Point to image */
(**aPixMap).rowBytes = bytesPerRow | /* MSB set for PixMap */
0x8000;
(**aPixMap).bounds = *bounds; /* Use given bounds */
(**aPixMap).pmVersion = 0; /* No special stuff */
(**aPixMap).packType = 0; /* Default PICT pack */
(**aPixMap).packSize = 0; /* Always zero in mem */
(**aPixMap).hRes = kDefaultRes; /* 72 DPI default res */
(**aPixMap).vRes = kDefaultRes; /* 72 DPI default res */
(**aPixMap).pixelSize = depth; /* Set # bits/pixel */
(**aPixMap).planeBytes = 0; /* Not used */
(**aPixMap).pmReserved = 0; /* Not used */
/* Initialize fields specific to indexed and direct PixMaps */
if (depth <= 8)
{
/* PixMap is indexed */
(**aPixMap).pixelType = 0; /* Indicates indexed */
(**aPixMap).cmpCount = 1; /* Have 1 component */
(**aPixMap).cmpSize = depth; /* Component size=depth */
(**aPixMap).pmTable = newColors; /* Handle to CLUT */
}
else
{
/* PixMap is direct */
(**aPixMap).pixelType = RGBDirect; /* Indicates direct */
(**aPixMap).cmpCount = 3; /* Have 3 components */
if (depth == 16)
(**aPixMap).cmpSize = 5; /* 5 bits/component */
else
(**aPixMap).cmpSize = 8; /* 8 bits/component */
(**newColors).ctSeed = 3 * (**aPixMap).cmpSize;
(**newColors).ctFlags = 0;
(**newColors).ctSize = 0;
(**aPixMap).pmTable = newColors;
}
}
else
error = MemError();
}
else
newColors = nil;
/* If no errors occured, return a handle to the new off-screen PixMap */
if (error != noErr)
{
if (newColors != nil)
DisposeCTable(newColors);
}
/* Return the error code */
return error;
}